package com.intelligent.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.intelligent.dto.ForgotPasswordDTO;
import com.intelligent.dto.LoginDTO;
import com.intelligent.dto.SmsCodeLoginDTO;
import com.intelligent.dto.SmsCodeSendDTO;
import com.intelligent.dto.UserPageQueryDTO;
import com.intelligent.entity.Role;
import com.intelligent.entity.User;
import com.intelligent.entity.UserRole;
import com.intelligent.exception.BusinessException;
import com.intelligent.feign.DeptApi;
import com.intelligent.mapper.TRoleMapper;
import com.intelligent.mapper.TUserRoleMapper;
import com.intelligent.mapper.UserMapper;
import com.intelligent.security.JwtUtil;
import com.intelligent.service.UserService;
import com.intelligent.util.SmsCodeUtils;
import com.intelligent.util.SmsUtils;
import com.intelligent.utils.MD5Utils;
import com.intelligent.vo.LoginVO;
import com.intelligent.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author lenovo
 * @description 针对表【t_user(系统用户表)】的数据库操作Service实现
 * @createDate 2025-08-26 11:51:45
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TUserRoleMapper userRoleMapper;
    @Autowired
    private TRoleMapper roleMapper;

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private SmsCodeUtils smsCodeUtils;

    @Autowired
    private DeptApi deptApi;

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        // 1. 根据用户名查询用户
        User user = getByUsername(loginDTO.getUsername());
        if (user == null) {
            throw new RuntimeException("用户名或密码错误,请重试"); // 实际项目建议用自定义异常
        }

        // 2. 校验用户状态（是否禁用）
        if (user.getStatus() == 0) {
            throw new RuntimeException("账号已禁用，请联系管理员");
        }

        // 3. 密码校验（用MD5Utils带盐加密，与数据库存储的密码对比）
        String inputPassword = loginDTO.getPassword();
        // 加密逻辑：MD5(MD5(输入密码) + 盐值) → 与数据库密码比对
        String encryptedInputPassword = MD5Utils.encodeWithSalt(inputPassword, "123456");
        if (!encryptedInputPassword.equals(user.getPassword())) {
            throw new RuntimeException("用户名或密码错误,请重试");
        }

        // 4. 查询用户权限列表（基于RBAC）
        List<String> permissions = getPermissionsByUserId(user.getUserId());

        // 5. 生成JWT Token（携带用户ID和用户账号）
        String token = JwtUtil.createToken(user.getUserId(), user.getUsername());

        // 6. 组装返回结果（脱敏用户信息）
        LoginVO loginVO = new LoginVO();
        loginVO.setToken(token);
        loginVO.setPermissions(permissions);

        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO); // 复制非敏感字段（如userId、username、realName）
        loginVO.setUserInfo(userVO);

        return loginVO;
    }

    @Override
    public User getByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public List<String> getPermissionsByUserId(Long userId) {
        return userMapper.selectPermissionsByUserId(userId);
    }

    @Override
    public String sendSmsCode(SmsCodeSendDTO sendDTO) {
        String phone = sendDTO.getPhone();
        // 生成6位验证码
        String code = smsCodeUtils.generateCode();

        // 调用短信工具类（控制台输出）
        boolean success = smsUtils.sendSmsCode(phone, code);
        if (!success) {
            throw new BusinessException("验证码生成失败");
        }

        // 存储到Redis，有效期3分钟
        smsCodeUtils.saveCodeToRedis(phone, code);

        return "验证码:" + code;
    }

    @Override
    public LoginVO smsCodeLogin(SmsCodeLoginDTO loginDTO) {
        String phone = loginDTO.getPhone();
        String inputCode = loginDTO.getCode();

        // 从Redis获取验证码
        String redisCode = smsCodeUtils.getCodeFromRedis(phone);
        if (redisCode == null) {
            throw new BusinessException("验证码已过期（3分钟），请重新获取");
        }

        // 校验验证码
        if (!inputCode.equals(redisCode)) {
            throw new BusinessException("验证码错误");
        }

        // 查询用户（根据实际业务调整）
        User user = userMapper.selectByPhone(phone);
        if (user == null) {
            throw new BusinessException("当前手机后未被任何员工使用");
        }
        // 生成Token等登录逻辑（携带用户ID和用户账号）
        String token = JwtUtil.createToken(user.getUserId(), user.getUsername());

        // 查询权限列表，保证与账号密码登录一致
        List<String> permissions = getPermissionsByUserId(user.getUserId());

        // 删除已使用的验证码
        smsCodeUtils.deleteCodeFromRedis(phone);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO); // 复制非敏感字段（如userId、username、realName）
        // 组装并返回登录结果
        LoginVO loginVO = new LoginVO();
        loginVO.setToken(token);
        loginVO.setUserInfo(userVO);
        loginVO.setPermissions(permissions);
        return loginVO;
    }

    @Override
    public String getRoleName(Long userId) {
        QueryWrapper<UserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        UserRole userRole = userRoleMapper.selectOne(queryWrapper);
        Role role = roleMapper.selectById(userRole.getRoleId());
        return role.getRoleName();
    }

    @Override
    public void updatePassword(ForgotPasswordDTO passwordDTO) {
        String phone = passwordDTO.getPhone();
        User user = userMapper.selectByPhone(phone);
        String encryptedInputPassword = MD5Utils.encodeWithSalt(passwordDTO.getNewPassword(), "123456");
        user.setPassword(encryptedInputPassword);
        System.out.println(encryptedInputPassword);
        userMapper.updateById(user);
    }

    @Override
    public void updatePhone(Long userId, SmsCodeLoginDTO loginDTO) {
        String newPhone = loginDTO.getPhone();
        String inputCode = loginDTO.getCode();

        // 1) 校验验证码
        String redisCode = smsCodeUtils.getCodeFromRedis(newPhone);
        if (redisCode == null) {
            throw new BusinessException("验证码已过期（3分钟），请重新获取");
        }
        if (!inputCode.equals(redisCode)) {
            throw new BusinessException("验证码错误");
        }

        // 2) 唯一性校验：新手机号不能被其他用户占用
        User exists = userMapper.selectByPhone(newPhone);
        if (exists != null && !exists.getUserId().equals(userId)) {
            throw new BusinessException("该手机号已被其他账号使用");
        }

        // 3) 更新当前登录用户的手机号
        User toUpdate = new User();
        toUpdate.setUserId(userId);
        toUpdate.setPhone(newPhone);
        userMapper.updateById(toUpdate);

        // 4) 清理已使用的验证码
        smsCodeUtils.deleteCodeFromRedis(newPhone);
    }

    @Override
    public java.util.Map<String, Object> pageUsers(UserPageQueryDTO query) {
        long pageNum = query.getPageNum();
        long pageSize = query.getPageSize();
        String keyword = query.getKeyword();
        Integer status = query.getStatus();
        Integer deptId = query.getDeptId();
        // 创建时间范围，仅使用 createTime 数组（大小为2）
        String beginTime = null;
        String endTime = null;
        if (query.getCreateTime() != null && query.getCreateTime().size() == 2) {
            beginTime = query.getCreateTime().get(0);
            endTime = query.getCreateTime().get(1);
            // 兼容仅传日期（yyyy-MM-dd）的情况
            if (beginTime != null && beginTime.length() == 10) {
                beginTime = beginTime + " 00:00:00";
            }
            if (endTime != null && endTime.length() == 10) {
                endTime = endTime + " 23:59:59";
            }
        }

        // 参数兜底与限流，防止 pageSize<=0 导致不分页
        if (pageNum < 1)
            pageNum = 1;
        if (pageSize < 1)
            pageSize = 10; // 默认页大小
        if (pageSize > 200)
            pageSize = 200; // 上限保护，避免大页拉全表

        Page<User> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
        if (keyword != null && !keyword.isEmpty()) {
            qw.and(w -> w.like(User::getUsername, keyword)
                    .or().like(User::getRealName, keyword)
                    .or().like(User::getPhone, keyword)
                    .or().like(User::getUserCode, keyword));
        }
        if (status != null) {
            qw.eq(User::getStatus, status);
        }
        if (deptId != null) {
            qw.eq(User::getDeptId, deptId);
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (beginTime != null && !beginTime.isEmpty()) {
            try {
                Date bt = sdf.parse(beginTime);
                qw.ge(User::getCreateTime, bt);
            } catch (Exception ignored) {
            }
        }
        if (endTime != null && !endTime.isEmpty()) {
            try {
                Date et = sdf.parse(endTime);
                qw.le(User::getCreateTime, et);
            } catch (Exception ignored) {
            }
        }

        this.page(page, qw);
        List<User> records = page.getRecords();
        for (User u : records) {
            try {
                u.setRoleName(getRoleName(u.getUserId()));
                if (u.getDeptId() != null) {
                    u.setDeptName(deptApi.getById(u.getDeptId()).getDepartmentName());
                }
                u.setPassword(null);
            } catch (Exception e) {
                // 忽略部门名拉取失败等非关键错误，避免分页整体失败
            }
        }

        java.util.Map<String, Object> data = new HashMap<>();
        data.put("total", page.getTotal());
        data.put("records", records);
        return data;
    }

    @Override
    public Long addUser(User user) {
        if (user == null) {
            throw new BusinessException("参数为空");
        }
        // 用户名唯一校验（如提供了用户名）
        if (user.getUsername() != null && !user.getUsername().isEmpty()) {
            User exists = userMapper.selectByUsername(user.getUsername());
            if (exists != null) {
                throw new BusinessException("用户名已存在");
            }
        }

        // 按数据库规则生成用户编号：AA0001、AA0002 ...
        Integer maxSeq = userMapper.selectMaxUserCodeSeq();
        int next = (maxSeq == null ? 0 : maxSeq) + 1;
        String code = String.format("AA%04d", next);
        user.setUserCode(code);
        user.setCreateTime(new java.util.Date());

        // 默认启用状态
        if (user.getStatus() == null) {
            user.setStatus(1);
        }

        // 避免客户端传入不可控字段
        user.setPassword(user.getPassword()); // 如果需要初始密码策略，可在此设置

        // 保存
        this.save(user);
        //
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getUserId());
        userRole.setRoleId(user.getRoleId());
        userRoleMapper.insert(userRole);
        return user.getUserId();
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        if (user == null || user.getUserId() == null) {
            throw new BusinessException("参数错误：缺少用户ID");
        }

        // 1) 更新用户基本信息
        this.updateById(user);

        // 2) 清理原有用户-角色关联
        QueryWrapper<UserRole> removeQw = new QueryWrapper<>();
        removeQw.eq("user_id", user.getUserId());
        userRoleMapper.delete(removeQw);

        // 3) 重新建立关联（若前端传了新的 roleId）
        if (user.getRoleId() != null) {
            UserRole ur = new UserRole();
            ur.setUserId(user.getUserId());
            ur.setRoleId(user.getRoleId());
            userRoleMapper.insert(ur);
        }
    }

    @Override
    @Transactional
    public void deleteUser(Long userId) {
        if (userId == null) {
            throw new BusinessException("参数错误：缺少用户ID");
        }

        // 1) 删除用户-角色关联
        QueryWrapper<UserRole> removeQw = new QueryWrapper<>();
        removeQw.eq("user_id", userId);
        userRoleMapper.delete(removeQw);

        // 2) 删除用户
        userMapper.deleteById(userId);
    }
}
